home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / share / doc / sg3-utils / examples / archive / llseek.c next >
Encoding:
C/C++ Source or Header  |  2004-08-23  |  3.2 KB  |  122 lines

  1. /*
  2.  * llseek.c -- stub calling the llseek system call
  3.  *
  4.  * Copyright (C) 1994 Remy Card.  This file may be redistributed
  5.  * under the terms of the GNU Public License.
  6.  *
  7.  * This file is borrowed from the util-linux-2.11z tarball's implementation
  8.  * of fdisk. It allows seeks to 64 bit offsets, if supported.
  9.  * Changed "ext2_" prefix to "llse".
  10.  */
  11. #define _XOPEN_SOURCE 500
  12. #define _GNU_SOURCE
  13.  
  14. #include <sys/types.h>
  15.  
  16. #include <errno.h>
  17. #include <unistd.h>
  18.  
  19. #if defined(__GNUC__) || defined(HAS_LONG_LONG)
  20. typedef long long       llse_loff_t;
  21. #else
  22. typedef long            llse_loff_t;
  23. #endif
  24.  
  25. extern llse_loff_t llse_llseek (unsigned int, llse_loff_t, unsigned int);
  26.  
  27. #ifdef __linux__
  28.  
  29. #ifdef HAVE_LLSEEK
  30. #include <syscall.h>
  31.  
  32. #else   /* HAVE_LLSEEK */
  33.  
  34. #if defined(__alpha__) || defined(__ia64__)  || defined(__s390x__)
  35.  
  36. #define my_llseek lseek
  37.  
  38. #else
  39. #include <linux/unistd.h>       /* for __NR__llseek */
  40.  
  41. static int _llseek (unsigned int, unsigned long,
  42.                    unsigned long, llse_loff_t *, unsigned int);
  43.  
  44. #ifdef __NR__llseek
  45.  
  46. static _syscall5(int,_llseek,unsigned int,fd,unsigned long,offset_high,
  47.                  unsigned long, offset_low,llse_loff_t *,result,
  48.                  unsigned int, origin)
  49.  
  50. #else
  51.  
  52. /* no __NR__llseek on compilation machine - might give it explicitly */
  53. static int _llseek (unsigned int fd, unsigned long oh,
  54.                     unsigned long ol, llse_loff_t *result,
  55.                     unsigned int origin) {
  56.         errno = ENOSYS;
  57.         return -1;
  58. }
  59.  
  60. #endif
  61.  
  62. static llse_loff_t my_llseek (unsigned int fd, llse_loff_t offset,
  63.                 unsigned int origin)
  64. {
  65.         llse_loff_t result;
  66.         int retval;
  67.  
  68.         retval = _llseek (fd, ((unsigned long long) offset) >> 32,
  69.                         ((unsigned long long) offset) & 0xffffffff,
  70.                         &result, origin);
  71.         return (retval == -1 ? (llse_loff_t) retval : result);
  72. }
  73.  
  74. #endif /* __alpha__ */
  75.  
  76. #endif  /* HAVE_LLSEEK */
  77.  
  78. llse_loff_t llse_llseek (unsigned int fd, llse_loff_t offset,
  79.                          unsigned int origin)
  80. {
  81.         llse_loff_t result;
  82.         static int do_compat = 0;
  83.  
  84.         if (!do_compat) {
  85.                 result = my_llseek (fd, offset, origin);
  86.                 if (!(result == -1 && errno == ENOSYS))
  87.                         return result;
  88.  
  89.                 /*
  90.                  * Just in case this code runs on top of an old kernel
  91.                  * which does not support the llseek system call
  92.                  */
  93.                 do_compat = 1;
  94.                 /*
  95.                  * Now try ordinary lseek.
  96.                  */
  97.         }
  98.  
  99.         if ((sizeof(off_t) >= sizeof(llse_loff_t)) ||
  100.             (offset < ((llse_loff_t) 1 << ((sizeof(off_t)*8) -1))))
  101.                 return lseek(fd, (off_t) offset, origin);
  102.  
  103.         errno = EINVAL;
  104.         return -1;
  105. }
  106.  
  107. #else /* !linux */
  108.  
  109. llse_loff_t llse_llseek (unsigned int fd, llse_loff_t offset,
  110.                          unsigned int origin)
  111. {
  112.         if ((sizeof(off_t) < sizeof(llse_loff_t)) &&
  113.             (offset >= ((llse_loff_t) 1 << ((sizeof(off_t)*8) -1)))) {
  114.                 errno = EINVAL;
  115.                 return -1;
  116.         }
  117.         return lseek (fd, (off_t) offset, origin);
  118. }
  119.  
  120. #endif  /* linux */
  121.  
  122.